package com.cxf.windex.base.util;

import com.alibaba.fastjson.JSON;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 * @author chenxf
 * @date 3/16/2018
 * @description
 */
public class WxUtil {
  private static RestTemplate restTemplate = new RestTemplate();

  public static final org.slf4j.Logger logger = LoggerFactory.getLogger(WxUtil.class);

  private  static String wxUrl="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
  private static String wxUserInfoUrl="https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";
  private static String wxTokenUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
  private static String wxDownloadUrl="http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
  private static String wxOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  private static String wxTicketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

  private static String wxGZHUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=PAGE&scope=snsapi_base&state=yunnying#wechat_redirect";

  private static String minaCodeUrl="https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN";
  private static String minaCodeUrlB="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN";

  private static String timeformat = "yyyyMMddHHmmss";
  private static int timeexpire = 1;

  private static String appKey = "junengzhongchuanlk100624xingfen2";


  public static String getGZHUrl(String appid,String page){
    return  wxGZHUrl.replace("APPID", appid).replace("PAGE", page);
  }

  /**
   * 获取微信openid 详细信息 公众号功能
   * @param appid appid
   * @param secret secret
   * @param openId openId
   * @return
   *   err:  {"errcode":40013,"errmsg":"invalid appid, hints: [ req_id: 0PFNQa0729th42 ]"}
   *   success:{"session_key":"R+AJs7g+f5841HSn51W0bA==","openid":"oLw0k0Ss_Ntjj-o5KT13L8PcXbsU"}
   */
  public static Map<String, String>  getOpenIdDetail(String appid,String secret, String openId){
    String accessToken=getWxToken(appid,secret);
    String requestUrl =
            wxUserInfoUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
    String oauth = restTemplate.getForObject(requestUrl, String.class);
    System.out.println("oauth:"+oauth);
    try {

      oauth=new String(oauth.getBytes("ISO-8859-1"),"UTF-8");
      return (Map<String, String>)JSON.parseObject(oauth,Map.class);

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  /**
   * 获取微信openid
   * @param appid appid
   * @param secret secret
   * @param jscode jscode
   * @return
   *   err:  {"errcode":40013,"errmsg":"invalid appid, hints: [ req_id: 0PFNQa0729th42 ]"}
   *   success:{"session_key":"R+AJs7g+f5841HSn51W0bA==","openid":"oLw0k0Ss_Ntjj-o5KT13L8PcXbsU"}
   */
  public static Map<String, String>  getOpenId(String appid,String secret, String jscode){
    String requestUrl =
        wxUrl.replace("APPID", appid).replace("SECRET", secret).replace("CODE", jscode);
    String oauth = restTemplate.getForObject(requestUrl, String.class);
    System.out.println("oauth:"+oauth);
    try {
       return (Map<String, String>)JSON.parseObject(oauth,Map.class);

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  public static String getWxToken(String appid,String secret) {
    String requestUrl =
        wxTokenUrl.replace("APPID", appid).replace("SECRET", secret);

    String oauth = restTemplate.getForObject(requestUrl, String.class);
    System.out.println("oauth:"+oauth);
    try {
      return ((Map<String, String>)JSON.parseObject(oauth,Map.class)).get("access_token");

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  public static String getWxTicket(String accessToken) {
    String requestUrl =
        wxTicketUrl.replace("ACCESS_TOKEN", accessToken);

    String oauth = restTemplate.getForObject(requestUrl, String.class);
    try {
      return ((Map<String, String>)JSON.parseObject(oauth,Map.class)).get("ticket");

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  public static Map<String, String> sign(String appid,String secret,String url) {

    String jsapiTicket = getWxTicket(getWxToken(appid,secret));

    Map<String, String> ret = new HashMap<String, String>();
    String nonce_str = createNonceStr();
    String timestamp = createTimestamp();
    String string1;
    String signature = "";

    // 注意这里参数名必须全部小写，且必须有序
    string1 =
        "jsapi_ticket=" + jsapiTicket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp
            + "&url=" + url;
    try {
      MessageDigest crypt = MessageDigest.getInstance("SHA-1");
      crypt.reset();
      crypt.update(string1.getBytes("UTF-8"));
      signature = byteToHex(crypt.digest());
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    ret.put("url", url);
    ret.put("nonceStr", nonce_str);
    ret.put("timestamp", timestamp);
    ret.put("signature", signature);
    ret.put("appid", appid);

    return ret;
  }

  /**
   * 获取媒体文件
   * @param appid appid
   * @param secret secret
   * @param mediaId 媒体文件id
   * @param savePath 文件在本地服务器上的存储路径

   * */
  public static String downloadMedia(String appid,String secret,String mediaId, String savePath) {

    String accessToken = getWxToken(appid,secret);
    System.out.println(":" + accessToken);
    String filePath = null;
    // 拼接请求地
    String requestUrl = wxDownloadUrl.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId);
    try {
      URL url = new URL(requestUrl);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setDoInput(true);
      conn.setRequestMethod("GET");
      File path = new File(savePath);
      if (!path.exists()) {
        path.mkdirs();
      }
      if (!savePath.endsWith("/")) {
        savePath += "/";
      }

      // 根据内容类型获取扩展名
      String fileExt = getFileexpandedName(conn.getHeaderField("Content-Type"));
      // 将mediaId作为文件名
      filePath = savePath + mediaId + fileExt;
      BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
      FileOutputStream fos = new FileOutputStream(new File(filePath));
      byte[] buf = new byte[8096];
      int size = 0;
      while ((size = bis.read(buf)) != -1) {
        fos.write(buf, 0, size);
      }
      fos.close();
      bis.close();

      conn.disconnect();
      String info = String.format("下载媒体文件成功，filePath=" + filePath);

      return mediaId + fileExt;
    } catch (Exception e) {
      filePath = null;
      String error = String.format("下载媒体文件失败：%s", e);
      System.out.println(error);
    }
    return mediaId;
  }

  /**
   * 根据内容类型判断文件扩展名
   *
   * @param contentType 内容类型
   * @return
   */
  public static String getFileexpandedName(String contentType) {
    switch (contentType) {
      case "image/jpeg":
        return ".jpg";
      case "audio/mpeg":
        return ".mp3";
      case "audio/amr":
        return ".amr";
      case "video/mp4":
        return ".mp4";
      case "video/mpeg4":
        return ".mp4";
      default:
        return ".jpg";
    }
  }



  public static String getMinaSign(String appid ,String timestamp,String nonceStr,String prepayId,String key) throws Exception {
    StringBuffer sb = new StringBuffer();
    sb.append("appId=" + appid)
        .append("&timeStamp=" + timestamp)
        .append("&nonceStr=" + nonceStr)
        .append("&package=prepay_id=" + prepayId)
        .append("&signType=MD5" )
        .append("&key=" + key);
    logger.debug("url={}",sb.toString());
    return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
  }

  public static byte[] getMinaCode(String appid,String secret,Map<String,String> param){
    String accessToken = getWxToken(appid,secret);
    String requestUrl =
        minaCodeUrl.replace("ACCESS_TOKEN", accessToken);

    try {
      MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
      HttpEntity requestEntity = new HttpEntity(param, headers);
      ResponseEntity<byte[]> entity = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
      logger.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());



//      Path path = Paths.get("d:/upload/xcx.jpg");
//      Files.write(path, entity.getBody());
      // postForObject(requestUrl,postStr ,"POST",String.class);
      logger.debug(" result={}",entity.getBody());
      return entity.getBody();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static byte[] getMinaCodeB(String appid,String secret,Map<String,String> param){
    String accessToken = getWxToken(appid,secret);
    String requestUrl =
        minaCodeUrlB.replace("ACCESS_TOKEN", accessToken);

    try {
      MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
      HttpEntity requestEntity = new HttpEntity(param, headers);
      ResponseEntity<byte[]> entity = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
      logger.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
      //logger.debug(" result={}",entity.getBody());
      return entity.getBody();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }


  public static void main(String[] args) {
   Map m= WxUtil.getOpenIdDetail("wxe82e8e016edc2f0f","28ed49be53cb56abba5077004c0d120d","o_xIE1mpvHMFABHznOF0tadHUfTo");
    logger.debug("result={}",m);
    //WxUtil.sign("wxe82e8e016edc2f0f","28ed49be53cb56abba5077004c0d120d","http://localhost:8771/weixin/weix.html");
 }

  private static String createNonceStr() {
    String codeSet = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char[] codes = new char[16];
    for (int i = 0; i < 16; i++) {
      codes[i] = codeSet.charAt(new Random().nextInt(codeSet.length() - 1));
    }
    return String.copyValueOf(codes);
  }
  private static  String byteToHex(final byte[] hash) {
    Formatter formatter = new Formatter();
    for (byte b : hash) {
      formatter.format("%02x", b);
    }
    String result = formatter.toString();
    formatter.close();
    return result;
  }

  private static String createTimestamp() {
    return Long.toString(System.currentTimeMillis() / 1000);
  }
}
